package org.eclipse.soc.ide4edu.assignment.operations;

import java.io.File;
import java.io.IOException;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.FilePartSource;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;

/**
 * This class contains methods for Authentication and Uploading the Assignment
 * 
 * @author Souvik Roy
 * 
 */
public class UploadOperation {

	/* Apache HttpClient instances */
	HttpClient client;
	PostMethod post;
	GetMethod get;
	/* End */

	/* Members */
	private String path;
	private String username;
	private String password;
	private String loginURL;
	private String sesskey;
	private String assignmentName;

	/* LoginMap instance for authentication */
	LoginMap lMap;

	/**
	 * 
	 * @param name
	 *            The Assignment Name
	 * @param loginURL
	 *            The String representation of the Login URL
	 * @param path
	 *            The Assignment's Path
	 */
	public UploadOperation(String name, String loginURL, String path) {

		this.loginURL = loginURL;
		this.path = path;
		assignmentName = name;
		lMap = new LoginMap();
	}

	/**
	 * 
	 * @param username
	 *            The Username
	 * @param password
	 *            The Password
	 * @return true if authentication was successful.
	 */
	public boolean authenticate(String username, String password) {

		this.username = username;
		this.password = password;

		try {
			client = new HttpClient();
			post = new PostMethod(loginURL);

			post.addParameter("username", username);
			post.addParameter("password", password);

			int statusCode = client.executeMethod(post);

			if (statusCode == -1) {
				showErrorDialog("Connection Error (Status Code -1)");
				return false;
			}

		} catch (Exception e) {
			showErrorDialog(e.getMessage());
		}

		return true;
	}

	/**
	 * 
	 * @param url
	 *            The URL where the Files reside in the server
	 * @return The 10 byte session key of the current session
	 * @throws HttpException
	 * @throws IOException
	 */
	private String getSessionKey(String url) throws HttpException, IOException {

		get = new GetMethod(url);
		client.executeMethod(get);

		String t = get.getResponseBodyAsString();
		int start = t.indexOf("name=\"sesskey\" value=\"") + 22;
		int end = start + 10;

		sesskey = t.substring(start, end);

		return sesskey;

	}

	/**
	 * Opens an Message Box with an Error Message
	 * 
	 * @param msg
	 *            The Error Message to be displayed
	 */
	private void showErrorDialog(String msg) {
		MessageBox msgBox = new MessageBox(new Shell(), SWT.ABORT);
		msgBox.setText("Connection Error");
		msgBox.setMessage(msg);
		msgBox.open();
	}

	/**
	 * Opens an Message Box to display a Message
	 * 
	 * @param msg
	 *            The Message to be displayed
	 */
	private void showMsgDialog(String msg) {
		MessageBox msgBox = new MessageBox(new Shell(), SWT.ABORT);
		msgBox.setText("Success");
		msgBox.setMessage(msg);
		msgBox.open();

	}

	/**
	 * Uploads the Zipped Assignment onto the Server. Ends the Session in the end.
	 * @param url The URL where Files are to be uploaded
	 * @throws IOException
	 */
	public void uploadFile(String url) throws IOException {

		sesskey = getSessionKey(url);

		File file = new File(path);

		post = new PostMethod(url);

		FilePartSource source = new FilePartSource(file);

		Part[] parts = { new StringPart("choose", ""),
				new StringPart("id", "3"), new StringPart("wdir", ""),
				new StringPart("MAX_FILE_SIZE", "2097152"),
				new StringPart("action", "upload"),
				new StringPart("sesskey", sesskey),
				new StringPart("save", "true"),
				new FilePart("userfile", source) };

		post.setRequestEntity(new MultipartRequestEntity(parts, post
				.getParams()));

		if (client.executeMethod(post) != -1)
			showMsgDialog("File Uploaded Successfully :)");
		else
			showErrorDialog("Upload Error :(");

		post.releaseConnection();
		get.releaseConnection();

	}
}
